package edu.usc.libtalk;

import java.util.ArrayList;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.RelativeLayout;
import android.widget.ZoomControls;
import edu.usc.libtalk.task.GetJSONObjectTask;
import edu.usc.libtalk.utils.ApplicationService;
import edu.usc.libtalk.utils.InternalConstant;
import edu.usc.libtalk.utils.SeatObject;

public class SSLOneActivity extends Activity implements InternalConstant, OnTouchListener{
	private int mode; // 0: Chat mode, 1: Sign in mode
	private String library;
	private int user_level;
	private int user_seat;
	private String username;
	Intent intent;
	private static final String TAG = "SSLOneActivity";	
	private static final float width = 540f;
	private static final float height = 956f;
    // These matrices will be used to scale the canvas image
    Matrix matrix = new Matrix();
    Matrix savedMatrix = new Matrix();
    ArrayList<SeatObject> activeSeats = new ArrayList<SeatObject>();
    
	
    
    // increment/decrement values
    /*private float zoomValue = 1f;
    private ImageView libImage;
    PointF mid = new PointF();
    
    private float clickedX;
    private float clickedY;
    
    public void onCreate(Bundle savedInstance) {
    	super.onCreate(savedInstance);
    	setContentView(R.layout.activity_ssl_one);
    	
        ZoomControls zoomControls = null;
        zoomControls = (ZoomControls)findViewById(R.id.zoomControlsOne);
        
        libImage = (ImageView)findViewById(R.id.image_ssl_one);
        libImage.setScaleType(ImageView.ScaleType.MATRIX);
        
        mid.x = (float) (width/2.0);
        mid.y = (float) (height/2.0);
       
        zoomControls.setOnZoomInClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            	zoomValue += 0.5f;
            	matrix.set(savedMatrix);
            	matrix.postScale(zoomValue, zoomValue, mid.x, mid.y);
            	libImage.setImageMatrix(matrix);
            }
        });
        
        zoomControls.setOnZoomOutClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
            	 if (zoomValue <= 1.0)
            		 zoomValue = 1f;
            	 else
            		 zoomValue -= 0.5f;
            	 matrix.set(savedMatrix);
            	 matrix.postScale(zoomValue, zoomValue, mid.x, mid.y);
            	 libImage.setImageMatrix(matrix);
             }
        }); 
        
        libImage.setOnTouchListener(new View.OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_DOWN) {
					clickedX = event.getX();
					clickedY = event.getY();
					System.out.println("Clicked X: " + clickedX);
					System.out.println("Clicked Y: " + clickedY);
				}
				return true;
			}
		});
    }*/
	
	SfcView sView;

    PointF mid = new PointF();
    protected float zoomValue = 1f;
    protected float clickedX;
    protected float clickedY;
    protected float translateX;
    protected float translateY;
    protected boolean zoomClicked = false;
    protected boolean mapClicked = false;
    protected boolean translating = false;
    private Camera cam = new Camera();

    @Override
    public void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
    	initSeats();
    	RelativeLayout rLayout = new RelativeLayout(this);
    	
    	sView = new SfcView(this);
    	sView.setOnTouchListener(this);
    	sView.setScrollBarStyle(SfcView.SCROLLBARS_INSIDE_OVERLAY);
    	sView.setScrollbarFadingEnabled(true);
    	
    	ZoomControls zControls = new ZoomControls(this);
    	zControls.setEnabled(true);
    		
    	rLayout.addView(sView);
    	rLayout.addView(zControls);
    	
    	setContentView(rLayout);
    	
        mid.x = (float) (width/2.0);
        mid.y = (float) (height/2.0);
       
        zControls.setOnZoomInClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            	zoomValue += 0.5f;
            	zoomClicked = true;
            }
        });
        
        zControls.setOnZoomOutClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
            	 if (zoomValue <= 1.0) 
            		 zoomValue = 1f;
            	 else {
            		 zoomValue -= 0.5f;
            		 zoomClicked = true;
            	 }
             }
        });   	
    }
     
    /**
     * This method initializes the valid seat locations on the canvas.
     * The user is only allowed to click on valid places to activate a seat
     * if they click anywhere outside of a valid location, nothing happens.
     * This is how we restrict the users from making errors
     */
    private void initSeats() {
    	float[] xyCoords = new float[8];
    	
    	// first valid seat location
    	xyCoords[0] = 185f;
    	xyCoords[1] = 325f;
    	
    	xyCoords[2] = 138f;
    	xyCoords[3] = 248f;
    	
    	xyCoords[4] = 98f;
    	xyCoords[5] = 172f;
    	
    	xyCoords[6] = 55f;
    	xyCoords[7] = 94f;
    	
    	SeatObject seat1 = new SeatObject(1, 1f, xyCoords);
    	activeSeats.add(seat1);
    	
    	// TODO: add remaining seats below, the xy coordinates have to
    	// be hard-coded for each zoom level, unless there is time to
    	// figure out how to dynamically set these values.
    	
    }
    
    @Override
	protected void onPause() {
		super.onPause();
		sView.pause();
	}

	@Override
	protected void onResume() {
		super.onResume();
		sView.resume();
	}

	public class SfcView extends SurfaceView implements Runnable {
		
		Thread t = null;
		SurfaceHolder holder;
		boolean isItOk = false;
		Bitmap sslFloor1;
		Paint p = new Paint();
		
		public SfcView(Context context) {
			super(context);
			holder = getHolder();
			sslFloor1 = BitmapFactory.decodeResource(getResources(), 
								R.drawable.ic_ssl_library_first_floor_map);
		}

		@Override
		public void run() {
			while (isItOk == true) {
				// perform canvas drawing
				if (!holder.getSurface().isValid()){
					continue; // skip everything if surface is not valid
				}
				
				// zoom the canvas
				if (zoomClicked == true) {
					matrix.set(savedMatrix);
	            	matrix.postScale(zoomValue, zoomValue, mid.x, mid.y);			
				}
				
				// check to see if the user has clicked on the floor plan
				if (mapClicked == true) {
					updateUserClicks();
					if (translating) {
						cam.save();
						cam.translate(translateX, translateY, 0.0f);
					}
				}
				
				mapClicked = false;
				zoomClicked = false;
				Canvas c = holder.lockCanvas(null);
				/*
				synchronized (holder.lockCanvas()){
					onDraw(c);
				}
				*/
				
				c.drawColor(Color.BLACK);
				if (translating)
					cam.applyToCanvas(c);
				c.drawBitmap(sslFloor1, matrix, p);
				
				p.setStyle(Paint.Style.STROKE);
				p.setColor(Color.RED);
				p.setStrokeWidth(3);
				p.setTextSize(10f);
				for (int i = 0; i < activeSeats.size(); i++) {
					// this is where we determine if a seat has been selected
					// and weather or not to draw the selection on the canvas
					if (activeSeats.get(i).isActive) {
						SeatObject s = activeSeats.get(i);
						// draw the selected seat in the appropriate location
						// based on how much the user has zoomed in our out.
						if (zoomValue == 1f)
							
							c.drawRect(s.range[0], s.range[1], s.range[0]+17, s.range[1]+20, p);
						else if (zoomValue == 1.5f) 
							c.drawRect(s.range[2], s.range[3], s.range[2]+27, s.range[3]+32, p);
						else if (zoomValue == 2.0f)
							c.drawRect(s.range[4], s.range[5], s.range[4]+31, s.range[5]+44, p);
						else if (zoomValue == 2.5f)
							c.drawRect(s.range[6], s.range[7], s.range[6]+40, s.range[7]+56, p);
					}
					// TODO: draw a different shade rectangle if seat is inactive
				}
				holder.unlockCanvasAndPost(c);
				if (translating)
					cam.restore();
			}		
		}
		
		public void updateUserClicks() {
			for (int i = 0; i < activeSeats.size(); i++) {
				SeatObject s = activeSeats.get(i);
				if (s.isSelected(clickedX, clickedY, zoomValue)) {
					break;
				}
			}
		}
    	
		public void pause() {
			isItOk = false;
			while(true) {
				try {
					t.join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				break;
			}
			t = null;
		}
		
		public void resume() {
			isItOk = true;
			t = new Thread(this);
			t.start();
		}
    }
	
	@Override
	public boolean onTouch(View v, MotionEvent event) {
		switch(event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			clickedX = event.getX();
			clickedY = event.getY();
			System.out.println("Clicked X: " + clickedX);
			System.out.println("Clicked Y: " + clickedY);
			mapClicked = true;
			break;
		case MotionEvent.ACTION_MOVE:
			translateX = event.getX();
			translateY = event.getY();
			System.out.println("Trans X: " + translateX);
			System.out.println("Trans Y: " + translateY);
			translating = true;
			break;
		case MotionEvent.ACTION_UP:
			clickedX = event.getX();
			clickedY = event.getY();
			translating = false;
			break;
		}	
		
		if (event.getActionIndex() == MotionEvent.ACTION_MOVE) {
			clickedX = event.getX();
			clickedY = event.getY();
			System.out.println("Clicked X: " + clickedX);
			System.out.println("Clicked Y: " + clickedY);
		}
		return true;
	}
    
	public void alertSignInDialog (int level, int seat) 
	{
		final int selected_level = level;
		final int selected_seat = seat;
		
		AlertDialog.Builder alertDialog = new AlertDialog.Builder(SSLOneActivity.this);
		alertDialog.setTitle("Locate yourself");
		alertDialog.setMessage("Is your location at " + library + " on level " + selected_level + " on seat " + selected_seat + " ?");
		
		alertDialog.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface arg0, int arg1) {
				ApplicationService.setLevel(1);
				ApplicationService.setSeat(selected_seat);
		        user_level = 1;
		        user_seat = selected_seat;
		        
		        updateUserSeat();
		    				
			}});
		
		alertDialog.setNegativeButton("Cancel", null);		
		
		alertDialog.show();
	}
	
    private void updateUserSeat(){
    	
    	intent = new Intent(SSLOneActivity.this, ChatActivity.class); 
    	String url = HOSTNAME + AUTHENTICATION_URL + "?devicetoken=" + ApplicationService.getDeviceID() + "&library=" + library + "&level=" + user_level + "&seat=" + user_seat + "&name=" + username;    	
    	
    	// Register the user with default name    	
    	new GetJSONObjectTask(){
    		@Override
    		protected void onPostExecute(JSONObject result){
				if(result == null){
					ApplicationService.inform(getString(R.string.nointernet));
					finish();
					return;
				}         		
				
				// Parse JSON Object				
                try{
                	String authen = result.getString("result");
                	
                	if((authen.length() != 0) && authen.equals("Success"))
                	{
                		startActivity(intent);
                	}else {
                		ApplicationService.inform("Connection errored");
    					finish();
    					return;                		
                	}
                	
                	
                }
                catch(JSONException e){
                	Log.e(TAG, "Error parsing data "+e.toString());
                }         		
         	}	
        }.execute(url.replaceAll(" ", "%20"));	
    }
    
	    @Override
	    public void onBackPressed()
	    {
			AlertDialog.Builder alertDialog = new AlertDialog.Builder(SSLOneActivity.this);
			alertDialog.setTitle("Exit this application");
			alertDialog.setMessage("Are you sure you want to close this application?");
			
			alertDialog.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface arg0, int arg1) {
					
					
						finish();
						SignInWithLocActivity.signInWithLocActivity.finish();
						SignInWithNameActivity.signInWithNameActivity.finish();
						SignInActivity.signinActivity.finish();
						LibListActivity.libListActivity.finish();
					
					
				}});
			
			alertDialog.setNegativeButton("Cancel", null);		
			
			if(mode==0)
			{
				alertDialog.show();
			}
			else
			{
				super.onBackPressed();
			}
	    }

}
